//Test for parser.
#include <fstream>
#include <iostream>
#include "XMLDocument.h"
#include "xmlexceptions.h"
#include <utility>
#include <memory>
#include <ctime>

clock_t startt;

				//doc.load_from_file("../../wurfl-2-short.xml");
				//doc.load_from_file("../../wurfl-2.xml");
				//doc.load_from_file("../../test.xml");

std::string filename = "../../wurfl-2.xml";
//std::string filename = "../../test.xml";
void start_timer() {
	startt = clock();
}

float end_timer() {
	return ( ((float)(clock()-startt))/CLOCKS_PER_SEC );
}

void Test1() {
    //XXX Don't really need err anymore...i'll have to remove it.
	float total;
	unsigned int n_times = 1;

	for (int i = 0; i < n_times; ++i){
		start_timer();
		xml_document doc;

		try {
			//doc.load_from_file("../../wurfl-2-short.xml");
			doc.load_from_file("../../wurfl-2.xml");
		    //doc.load_from_file("../../test.xml");
		}
		catch ( xml_validate_exception & e){
			printf("Error validating XML document\n");
			return;
		}
		catch ( xml_syntax_exception & e){
			printf("Error with syntax of XML\n");
			return;
		}
		catch ( xml_filenotfound_exception &e){
			printf("%s\n", e.what());
		}
		total += end_timer();
	}

	printf("Average time for %d times: %f\n", n_times, total/float(n_times) );
}

//Run this with and without C++ 11 optimizations
void Test2()
{
	xml_document doc;
	try {
		doc.load_from_file(filename);
		}
		catch ( xml_validate_exception & e){
			printf("Error validating XML document\n");
		}
		catch ( xml_syntax_exception & e){
			printf("Error with syntax of XML\n");
		}
		catch ( xml_filenotfound_exception &e){
			printf("%s\n", e.what());
		}
		{
		float total = 0.0f;
		unsigned int n = 100;
		for (int i = 0; i < n; ++i){
			start_timer();
			xmlnodes nodes = std::move(doc.get_elements_by_tag_name("device")); //move (constant)
			xmlnodes nodes2 = nodes; //no move, linear copy
			total += end_timer();

			//Just so it doesn't get optimized out.
			//printf("Num nodes: %d\n", nodes2.size());
		}
		
		printf("Average time for %d times: %f\n", n, total/float(n) );
		}

		//SEcond test
		{
		float total = 0.0f;
		unsigned int n = 100;
		for (int i = 0; i < n; ++i){
			start_timer();
			xmlnodes nodes = std::move(doc.get_elements_by_tag_name("device")); //move (constant)
			
			total += end_timer();

			//Just so it doesn't get optimized out.
			//printf("Num nodes: %d\n", nodes2.size());
		}
		
		printf("Average time for %d times: %f\n", n, total/float(n) );
		}


}


int main(int argc, char ** argv) {

	//Test1();
	Test2();

	int waitvar;
	std::cin >> waitvar;

	return 0;
}

// Create a typedef to the node type.
typedef std::shared_ptr<xmlnode> xmlnode_ptr;

// Load in a file
void main1 (int argc, char ** argv) {
	xml_document doc;

	try {
        doc.load_from_file("../../test.xml");
    }
    catch ( xml_validate_exception & e){
        printf("Error validating XML document\n");
    }
    catch ( xml_syntax_exception & e){
        printf("Error with syntax of XML\n");
    }
}

// Query the name and innertext of the node.
void main2 (int argc, char ** argv) {
	xml_document doc;

	try {
        doc.load_from_file("../../test.xml");
    }
    catch ( xml_validate_exception & e){
        printf("Error validating XML document\n");
    }
    catch ( xml_syntax_exception & e){
        printf("Error with syntax of XML\n");
    }

	// Query name of root.
	xmlnode_ptr root = doc.get_root_node();

	std::cout << "Name of root: " << root->get_name() << '\n';
	std::string innertext = root->get_innertext();
	if (innertext.length() != 0){
		std::cout << "Inner text: " << root->get_innertext() << '\n';
	}
}

// Query the attributes of a given node.
void main3 (int argc, char ** argv) {
	xml_document doc;

	try {
        doc.load_from_file("../../test.xml");
    }
    catch ( xml_validate_exception & e){
        printf("Error validating XML document\n");
    }
    catch ( xml_syntax_exception & e){
        printf("Error with syntax of XML\n");
    }

	// Query name of root.
	xmlnode_ptr root = doc.get_root_node();

	// xmlattributes is a typedef for std::vector< xmlattribute* >
	xmlattributes attrs = root->get_attributes();
	std::cout << "Number of attributes: " << attrs.size() << '\n';

	// Go through attributes and print name and value.
	for (int i = 0; i < attrs.size(); ++i){
		std::cout << "Attribute " << i << "'s name: " << attrs[i].get_name() << ", value: " << attrs[i].get_value() << '\n';
	}
}

// Query for all nodes with a specific name and print out its inner text
void main4 (int argc, char ** argv) {
	xml_document doc;

	try {
        doc.load_from_file("../../test.xml");
    }
    catch ( xml_validate_exception & e){
        printf("Error validating XML document\n");
    }
    catch ( xml_syntax_exception & e){
        printf("Error with syntax of XML\n");
    }

	// Query for all nodes with a specific name
	xmlnodes nodes = doc.get_elements_by_tag_name("book");

	// Print the number of books
	std::cout << "Number of elements with name of \"book\": " << nodes.size() << '\n';

	// Print the text of each node
	for (int i = 0; i < nodes.size(); ++i){
		std::cout << "Text of node " << i << ": " << nodes[i]->get_innertext() << '\n';
	}
}

// Get number of children of a particle node after retrieving it via its id.
void main5 (int argc, char ** argv) {
	xml_document doc;

	try {
        doc.load_from_file("../../test.xml");
    }
    catch ( xml_validate_exception & e){
        printf("Error validating XML document\n");
    }
    catch ( xml_syntax_exception & e){
        printf("Error with syntax of XML\n");
    }

	// This returns a collection of XML nodes.  It is possible to have multiple nodes with the same ID.
	xmlnodes specific_books = doc.get_elements_by_id("bk101");

	if (specific_books.size() != 0){
		unsigned int size = specific_books[0]->get_child_nodes().size();
		std::cout << "Number of children of book with ID bk101: " << size << '\n';
	}
}